useContext
🧑🏻💻 useContext
useContext
는 컴포넌트에서 context를 읽고 구독할 수 있게 해주는 React Hook이다.
✅ useContext 문법
const value = useContext(SomeContext)
SomeContext인
context
자체는 정보를 보유하지 않고, 상위<Context.Provider>
에서 제공하거나 읽을 수 있는 정보를 나타낸다.반환값은
createContext
에 전달한defaultValue
가 된다.반환된 값은 항상 최신 값이다.
🧑🏻💻 알고 가기
✅ context
- context는 prop drilling, 즉 prop를 계속해서 하위 컴포넌트로 내려주는 작업을 보완하고자 나왔다. 즉 아파트의 온수 시스템처럼 아파트라는 Provider 안에서 원하는 곳에서 쓸 수 있다는 것을 의미한다.
✅ useContext는 어떻게 동작하는가?
React는 context 값을 결정하기 위해 컴포넌트 트리를 검색하고, 특정 context 상위의 가장 가까운 context provider를 찾는다.
React는
context
가 변경되면context
를 받는 provider부터 해당context
를 읽는 자식들을 전부 자동으로 리렌더링한다.
✅ useContext를 언제 사용해야 하는가?
테마 설정 (다크모드)
로그인 상태 구현
✅ <Context.Provider>
사용 위치
useContext()
호출은 항상 해당 컴포넌트 위에 있는 가장 가까운 provider에서 값을 찾으므로, 해당<Context.Provider>
는useContext()
호출을 수행하는 컴포넌트의 위에 있어야 한다.
🧑🏻💻 활용 및 생각할 거리
✅ context
로 객체 및 함수 전달 시 리렌더링 최적화하는 방법
context
로 전달된 객체와 함수는 렌더링 시 다른 객체와 다른 함수가 된다. 이 때문에 기초 데이터가 변경되지 않았어도 해당context
를 읽는 자식들을 전부 자동으로 리렌더링되는 문제가 발생한다.따라서 리렌더링 최적화를 위해 함수를
useCallback
으로 감싸고 객체 생성은useMemo
로 감싸주어 사용하는 것이 좋다.
import { useCallback, useMemo } from 'react';
function MyApp() {
const [currentUser, setCurrentUser] = useState(null);
const login = useCallback((response) => {
storeCredentials(response.credentials);
setCurrentUser(response.user);
}, []);
const contextValue = useMemo(() => ({
currentUser,
login
}), [currentUser, login]);
return (
<AuthContext.Provider value={contextValue}>
<Page />
</AuthContext.Provider>
);
}
✅ useContext()와 useState()로 다크 모드 구현하기
- 부모 컴포넌트에
theme
state를 선언한 후 현재 state를 context 값으로 provider에 전달한다. - 하위 컴포넌트가 전달받은
theme
state를 업데이트하기 위해setTheme
함수를 호출하면 해당 state를 사용하는 컴포넌트들 모두 변경된 값으로 리렌더링된다.
function MyPage() {
const [theme, setTheme] = useState('dark');
return (
<ThemeContext.Provider value={theme}>
<Form />
<Button onClick={() => {
setTheme('light');
}}>
Switch to light theme
</Button>
</ThemeContext.Provider>
);
}